package com.example.module.web;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebSettings.RenderPriority;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.example.R;
import com.example.entity.Const;
import com.example.module.PicturePicker;
import com.example.module.widget.Snapshot;
import com.example.util.SharedPreferenceUtil;

public class WebBrowser extends LinearLayout {
	private static final String TAG = "WebBrowser";
	private static final int pickedRectPadding = 0;
	
	private CustomAddressBar addressBar;
	private ImageView bookmarkButton;
	private FrameLayout webViewBox;
	private CustomWebView webView;
	private FrameLayout webViewOverlay;
	private String currentUrl;
	
	public boolean isAnimationFinished;
	public boolean isPickerMode = false;
	
	private BrowserActionListener browserActionListener;
	private ImageView loadingImage;
	private ImageView upwardButton;
	private ImageView backwardButton;
	private ImageView forwardButton;
	private ImageView menuButton;
	private ImageView postButton;
	
	private float startY = 0, deltaY = 0;

	public interface BrowserActionListener {
		public void onBookmarkCheck(String url);
		public void onBookmarkClick();
		public void onOverlayClick();
		public void onMenuClick();
		public void onPickPicture(RectF pickedRect);
		public void onPostButtonClick();
		public void onPickerCanceled();
	}

	public WebBrowser(Context context) {
		super(context);
		initializeView(context);
		initializeAction(context);
	}
	
	public WebBrowser(Context context, AttributeSet attrs) {
		super(context, attrs);
		initializeView(context);
		initializeAction(context);
	}

	private void initializeView(Context context) {
		LayoutInflater.from(context).inflate(R.layout.web_browser, this, true);
		addressBar = (CustomAddressBar) findViewById(R.id.addressBar);
		menuButton = addressBar.getMenuButton();
		postButton = addressBar.getPostButton();
		bookmarkButton = addressBar.getBookmarkButton();
		
		loadingImage = (ImageView) findViewById(R.id.loadingImage);
		upwardButton = (ImageView) findViewById(R.id.upwardButton);
		backwardButton = (ImageView) findViewById(R.id.backwardButton);
		forwardButton = (ImageView) findViewById(R.id.forwardButton);
		webViewOverlay = (FrameLayout) findViewById(R.id.webViewOverlay);
		webViewBox = (FrameLayout) findViewById(R.id.webViewBox);
		
		webView = (CustomWebView) findViewById(R.id.webView);
		webView.requestFocus(View.FOCUS_DOWN);
		webView.setHorizontalScrollBarEnabled(false);
		webView.setVerticalScrollBarEnabled(true);
		webView.setVerticalScrollbarOverlay(true);
		WebSettings webSettings = webView.getSettings();
		if (webSettings != null) {
			webSettings.setRenderPriority(RenderPriority.HIGH);
			webSettings.setLoadsImagesAutomatically(true);
			webSettings.setBuiltInZoomControls(true); 
			webSettings.setSupportZoom(true); //상세 웹뷰에서만 사용
			webSettings.setJavaScriptEnabled(true);
			webSettings.setLoadWithOverviewMode(true);
			webSettings.setUseWideViewPort(true);

			webSettings.setDomStorageEnabled(true);
			webSettings.setDatabaseEnabled(true);
			webSettings.setDatabasePath(Const.WEB_DATABASE_PATH);
			webSettings.setAllowFileAccess(true);
			webSettings.setSupportMultipleWindows(false);
			webSettings.setAppCacheEnabled(true);
			webSettings.setAppCachePath(Const.WEB_CACHE_PATH);
			webSettings.setAppCacheMaxSize(10 * 1024 * 1024);
		}
	}
	
	private void initializeAction(Context context) {
		addressBar.setWebViewListener(new CustomAddressBar.WebViewListener() {
			@Override
			public void onLoad(String url) {
				webView.isPageLoading = true;
				webView.loadUrl(url);
			}
			
			@Override
			public void onLoadFinished() {
				webView.isPageLoading = false;
				restoreLoadingImage();
			}
		});

		menuButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (browserActionListener != null)
					browserActionListener.onMenuClick();
			}
		});
		
		postButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				View view = inflate(getContext(), R.layout.layout_picture_picker, getWebViewBox());
				
				isPickerMode  = true;
				if (browserActionListener != null)
					browserActionListener.onPostButtonClick();
				
				view.findViewById(R.id.okPcitureButton).setOnClickListener(new View.OnClickListener() {
					@Override
					public void onClick(View v) {
						Toast.makeText(getContext(), "OK click", Toast.LENGTH_SHORT).show();
						//TODO save picture
						
						PicturePicker picturePicker = (PicturePicker) findViewById(R.id.picturePicker);
						RectF pickedRect = picturePicker.getPcikedBounds();
						
						pickedRect.left = pickedRect.left + 2 + pickedRectPadding;
						pickedRect.top = pickedRect.top + 2 + pickedRectPadding;
						pickedRect.right = pickedRect.right - 2 - pickedRectPadding;
						pickedRect.bottom = pickedRect.bottom - 2 - pickedRectPadding;
						
						if (browserActionListener != null) {		
							browserActionListener.onPickPicture(pickedRect);
						}
					}
				});
				
				view.findViewById(R.id.cancelPcitureButton).setOnClickListener(new View.OnClickListener() {
					@Override
					public void onClick(View v) {
						Toast.makeText(getContext(), "Cancel click", Toast.LENGTH_SHORT).show();
						getWebViewBox().removeView(findViewById(R.id.picturePickerLayout));
						isPickerMode = false;
						
						if (browserActionListener != null)		
							browserActionListener.onPickerCanceled();
					}
				});
			}
		});
		
		bookmarkButton.setOnClickListener(new View.OnClickListener() {
 			@Override
 			public void onClick(View v) {
 				if (browserActionListener != null)
 					browserActionListener.onBookmarkClick();
 			}
 		});
		
		upwardButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				webView.scrollTo(0, 0);
			}
		});
		
		backwardButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (webView.canGoBack())
					webView.goBack();	
			}
		});
		
		forwardButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (webView.canGoForward())
					webView.goForward();
			}
		});

		webViewOverlay.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View view) {
				if (browserActionListener != null)
					browserActionListener.onOverlayClick();
			}
		});
		
        webView.setWebViewClient(new WebViewClient(){
	    	@Override
	    	public void onPageStarted(WebView view, String url, Bitmap favicon) {
	    		Log.d(TAG, "onPageStarted webView.isPageLoading=" + webView.isPageLoading + " url=" + url);
	    		webView.isPageLoading = true;
	    		addressBar.setAddressUrl(url);
	    		currentUrl = url;
	    		webView.requestFocus();
	    		webView.scrollTo(0, 0);
	    		
	    		if (browserActionListener != null)
	    			browserActionListener.onBookmarkCheck(url);
	    		
	    		super.onPageStarted(view, url, favicon);
	    	}
	    	
	    	@Override
	    	public void onPageFinished(WebView view, String url) {
	    		Log.d(TAG, "onPageFinished webView.isPageLoading=" + webView.isPageLoading + " url=" + url);
	    		webView.isPageLoading = false;
	    		SharedPreferenceUtil.putString(getContext(), "currentUrl", currentUrl);

	    		backwardButton.setVisibility(webView.canGoBack() ? View.VISIBLE : View.GONE);
	    		forwardButton.setVisibility(webView.canGoForward() ? View.VISIBLE : View.GONE);
	    		
	    		super.onPageFinished(view, url);
	    	}
        });
		
		webView.setWebChromeClient(new WebChromeClient() {
        	@Override
        	public void onProgressChanged(WebView view, int newProgress) {
        		super.onProgressChanged(view, newProgress);
        		webView.isPageLoading = true;
        		addressBar.changeAddressProgress(newProgress);
        	}
        });
		
		webView.setScrollListener(new CustomWebView.OnScrollListener() {
			
			@Override
			public void onScroll(int l, int t, int oldl, int oldt) {
				Log.d(TAG, "onScroll t=" + t);
				upwardButton.setVisibility(t > 10 ? View.VISIBLE : View.GONE);
			}
		});
	}
	
	public void restoreLoadingImage() {
		Log.d(TAG, "restoreLoadingImage");
		if (!webView.isPageLoading) {
			loadingImage.setImageResource(R.drawable.arrow_up_32);
			loadingImage.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 0));
			loadingImage.clearAnimation();
			
			startY = 0;
			deltaY = 0;	
		}
	}
	
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		if (!isPickerMode && !webView.isPageLoading) {
			final int action = ev.getAction();
			final float eventY = ev.getY();
			final int scrollY = webView.getScrollY();
			final int dragDistance = (int) (addressBar.getHeight() * 1.5);
			
			VelocityTracker velocity = VelocityTracker.obtain(); 
			
			Log.d(TAG, "ACTION ev=" + ev);
			
			switch (action) {
			case MotionEvent.ACTION_DOWN:
				if (scrollY == 0) {
					startY = eventY;
				}
				
				deltaY = 0;	
				
				Log.d(TAG, "ACTION_DOWN scrollY=" + scrollY + " deltaY=" + deltaY);
				break;

			case MotionEvent.ACTION_MOVE:
				Log.d(TAG, "ACTION_MOVE 1 scrollY=" + scrollY + " deltaY=" + deltaY);
				
				if (scrollY == 0) {
					velocity.addMovement(ev);
					velocity.computeCurrentVelocity(1000);
					float x_velocity = velocity.getXVelocity();
					float y_velocity = velocity.getYVelocity();
					Log.d(TAG, "ACTION_MOVE 1 x_velocity=" + x_velocity + " y_velocity=" + y_velocity);
					
					deltaY = (eventY - startY);
					if (deltaY > 0) {
						int height = Math.min(loadingImage.getHeight() + (int) deltaY, dragDistance);
						
						if (height >= 0 && height <= dragDistance) {
							Log.d(TAG, "height=" + height + " deltaY=" + deltaY);				
							
							loadingImage.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, height));
							if (height == dragDistance) {
								loadingImage.setImageResource(R.drawable.refresh_icon_32);
								Animation anim = AnimationUtils.loadAnimation(getContext(), R.anim.rotate_circle);
								anim.setDuration(1000);
								loadingImage.startAnimation(anim);
								webView.isPageLoading  = true;
								webView.reload();
							}
						}	
					}
				}
				
				startY = eventY;
				
				Log.d(TAG, "ACTION_MOVE 2 scrollY=" + scrollY + " deltaY=" + deltaY);
				break;
				
			case MotionEvent.ACTION_CANCEL:
			case MotionEvent.ACTION_UP:
				//TODO fix that
				Log.d(TAG, "ACTION_UP loadingImage.getHeight()=" + loadingImage.getHeight() + " < dragDistance=" + dragDistance);
				if (loadingImage.getHeight() < dragDistance)
					restoreLoadingImage();
				
				Log.d(TAG, "ACTION_UP scrollY=" + scrollY + " deltaY=" + deltaY);
				break;
			}
		}
		
		return super.dispatchTouchEvent(ev);
	}
	
	public void displayOverlay(boolean value) {
		webViewOverlay.setAnimation(AnimationUtils.loadAnimation(getContext(), value ? R.anim.fade_in : R.anim.fade_out));
		webViewOverlay.setVisibility(value ? View.VISIBLE : View.GONE);
		
		Log.d("displayOverlay", "value=" + value + " overlay.getVisibility()=" + webViewOverlay.getVisibility());
	}

	public BrowserActionListener getBrowserActionListener() {
		return browserActionListener;
	}

	public void setBrowserActionListener(BrowserActionListener browserActionListener) {
		this.browserActionListener = browserActionListener;
	}
	
	public CustomAddressBar getAddressBar() {
		return addressBar;
	}

	public void setAddressBar(CustomAddressBar addressBar) {
		this.addressBar = addressBar;
	}

	public ImageView getBookmarkButton() {
		return bookmarkButton;
	}

	public void setBookmarkButton(ImageView bookmarkButton) {
		this.bookmarkButton = bookmarkButton;
	}

	public FrameLayout getWebViewBox() {
		return webViewBox;
	}

	public void setWebViewBox(FrameLayout webViewBox) {
		this.webViewBox = webViewBox;
	}

	public CustomWebView getWebView() {
		return webView;
	}

	public void setWebView(CustomWebView webView) {
		this.webView = webView;
	}

	public FrameLayout getWebViewOverlay() {
		return webViewOverlay;
	}

	public void setWebViewOverlay(FrameLayout webViewOverlay) {
		this.webViewOverlay = webViewOverlay;
	}

	public String getCurrentUrl() {
		return currentUrl;
	}

	public void setCurrentUrl(String currentUrl) {
		this.currentUrl = currentUrl;
	}

	public void loadUrl(String url) {
		this.webView.loadUrl(url);
	}

	public void activateBookmark(boolean flag) {
		if (flag)
			bookmarkButton.setImageDrawable(getResources().getDrawable(R.drawable.star_on));
		else
			bookmarkButton.setImageDrawable(getResources().getDrawable(R.drawable.star_off));
		
		bookmarkButton.setSelected(flag);
	}

	public void animateBookmarkShot(Bitmap bitmap) {
		final Snapshot snapshot = new Snapshot(getContext());
		snapshot.setBackgroundDrawable(new BitmapDrawable(bitmap));
		webViewBox.addView(snapshot);
		snapshot.animateSpin(new Animation.AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {
				isAnimationFinished = false;
				Log.e("animateBookmarkShot", "onAnimationStart");
			}
			
			@Override
			public void onAnimationRepeat(Animation animation) {}
			
			@Override
			public void onAnimationEnd(Animation animation) {
				isAnimationFinished = true;
				Log.e("animateBookmarkShot", "onAnimationEnd");
				webViewBox.removeView(snapshot);
			}
		});
	}

	public void animateCaptureShot() {
		final Snapshot snapshot = new Snapshot(getContext());
		Drawable drawable = getResources().getDrawable(R.drawable.wind);
		drawable.setAlpha(190);
		snapshot.setBackgroundDrawable(drawable);
		
		webViewBox.addView(snapshot);
		snapshot.animateFade(new Animation.AnimationListener() {
			
			@Override
			public void onAnimationStart(Animation animation) {
				isAnimationFinished = false;
				Log.e("animateCaptureShot", "onAnimationStart");
			}
			
			@Override
			public void onAnimationRepeat(Animation animation) {}
			
			@Override
			public void onAnimationEnd(Animation animation) {
				Animation nextAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.flash);
				nextAnimation.setAnimationListener(new Animation.AnimationListener() {

					@Override
					public void onAnimationStart(Animation animation) {}

					@Override
					public void onAnimationRepeat(Animation animation) {}
					
					@Override
					public void onAnimationEnd(Animation animation) {
						isAnimationFinished = true;
					}
				});
				webView.startAnimation(nextAnimation);
				
				Log.e("animateCaptureShot", "onAnimationEnd");
				webViewBox.removeView(snapshot);
			}
		});
	}

}
